{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "dd376390",
   "metadata": {},
   "source": [
    "# [3、PyTorch张量的运算API（下）](https://www.bilibili.com/video/BV1Hq4y1R7dM?spm_id_from=333.788.player.switch&vd_source=cdd897fffb54b70b076681c3c4e4d45d)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "7e2d9881",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "661e9eb0",
   "metadata": {},
   "source": [
    "## [torch.dtype](https://docs.pytorch.org/docs/stable/tensor_attributes.html)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "34daa4ce",
   "metadata": {},
   "source": [
    "### 浮点数表示\n",
    "\n",
    "注意 float16 指数5位，而bf16 指数占8位就好了。bf16指数位和32位的一样大但是精度不同"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "2ee0c5fa",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[0, 2],\n",
       "        [1, 3]])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# transpose\n",
    "a = torch.arange(4).reshape((2,2))\n",
    "a.transpose(0, 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "77831900",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([4, 3, 1])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# take\n",
    "a = torch.tensor([[4,3], [2,1]])\n",
    "torch.take(a, torch.tensor([0,1,3]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "33c8a7a0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([1, 2, 3, 1, 2, 3])"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# tile 复制\n",
    "x = torch.tensor([1,2,3])\n",
    "x.tile((2,)) # 对dim=0拷贝2份"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8ceb2008",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[1, 2, 1, 2, 1, 2],\n",
       "        [3, 4, 3, 4, 3, 4]])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = torch.tensor([[1,2], [3,4]])\n",
    "x.tile((1,3)) # 对dim=1 拷贝3份"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "bbd8754b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[0, 1, 2],\n",
      "        [3, 4, 5]])\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "tensor([[0, 3],\n",
       "        [1, 4],\n",
       "        [2, 5]])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 交换维度\n",
    "a = torch.arange(6).reshape((2,3))\n",
    "print(a)\n",
    "a.transpose(0, 1) # 交换第 0,1 维度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "9d560fae",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[0, 1, 2],\n",
      "        [3, 4, 5]])\n",
      "(tensor([0, 1, 2]), tensor([3, 4, 5]))\n",
      "(tensor([0, 3]), tensor([1, 4]), tensor([2, 5]))\n"
     ]
    }
   ],
   "source": [
    "# unbind：移除张量的维度，返回所有此维度的元组\n",
    "a = torch.arange(6).reshape((2,3))\n",
    "print(a)\n",
    "print(a.unbind(0))\n",
    "print(a.unbind(1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "d3233c75",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([1, 2, 3, 4]) torch.Size([4])\n",
      "tensor([[1, 2, 3, 4]]) torch.Size([1, 4])\n",
      "tensor([[1],\n",
      "        [2],\n",
      "        [3],\n",
      "        [4]]) torch.Size([4, 1])\n"
     ]
    }
   ],
   "source": [
    "# unsqueeze：新增一个维度(expand_dims)\n",
    "x = torch.tensor([1,2,3,4])\n",
    "print(x, x.shape)\n",
    "y = x.unsqueeze(0)\n",
    "print(y, y.shape)\n",
    "y = x.unsqueeze(1)\n",
    "print(y, y.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "b1adcdfa",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[-1.4589, -0.2763],\n",
      "        [ 0.9700,  0.5336],\n",
      "        [-0.1716, -1.1861]])\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "tensor([[0., 0.],\n",
       "        [1., 1.],\n",
       "        [0., 0.]])"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# where：根据条件返回 x 或者 y\n",
    "t = torch.randn(3,2)\n",
    "print(t)\n",
    "x = torch.ones_like(t)\n",
    "y = torch.zeros(1,2)\n",
    "torch.where(t > 0, x, y) # xy可以广播"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c59128c9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# manual_seed：指定随机种子，用于模型复现\n",
    "torch.manual_seed(42)\n",
    "print(torch.rand(2,3))\n",
    "# 如果使用cuda,那么会对GPU也设置好随机数\n",
    "# 注意使用numpy也需要设置随机种子"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a5b887e2",
   "metadata": {},
   "source": [
    "## 随机分布"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a1eba708",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[0., 0., 0.],\n",
       "        [0., 0., 0.],\n",
       "        [1., 0., 1.]])"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 伯努利分布\n",
    "# 将概率放入伯努利分布采样，返回 01\n",
    "torch.bernoulli(\n",
    "    torch.empty(3,3).uniform_(0, 1)\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5154c276",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[ 0.0000,  0.8063, -2.0934],\n",
       "        [-5.6108,  4.9884,  1.5667]])"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 高斯分布，可以指定均值和标准差\n",
    "torch.normal(\n",
    "    mean=torch.zeros(2,3), std=torch.arange(6).reshape(2,3)\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c962ca92",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[0.2246, 0.9354, 0.3367],\n",
      "        [0.9177, 0.8836, 0.6692]])\n",
      "tensor([[-1.8539, -1.1582,  0.2880],\n",
      "        [-0.8297, -0.0941,  1.4635]])\n",
      "tensor([3, 3, 4])\n",
      "tensor([0, 2, 3, 1])\n"
     ]
    }
   ],
   "source": [
    "# rand：从 [0-1) 区间的均匀分布\n",
    "# randn 从 [0-1) 区间的高斯分布\n",
    "# randperm：获得随机组合\n",
    "print(torch.rand(2,3))\n",
    "print(torch.randn(2,3))\n",
    "print(torch.randint(1,5, (3,)))\n",
    "print(torch.randperm(4)) # 一般用于构建数据集"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "dl",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
